import { create } from 'zustand'
import { subscribeWithSelector } from 'zustand/middleware'
import { Dataset, DatasetStats } from '@/types/dataset'
import { ImageData, ImageMetadata } from '@/types/image'
import { getApiClient } from '@/lib/mockApi'
import { ApiClientError } from '@/lib/apiError'

// 缓存接口
interface CacheEntry<T> {
    data: T
    timestamp: number
    expiresAt: number
}

// 加载状态类型
type LoadingState = 'idle' | 'loading' | 'success' | 'error'

// 错误信息接口
interface ErrorInfo {
    message: string
    code?: string
    details?: Record<string, unknown>
    timestamp: number
}

export interface ImageStore {
    // 数据状态
    datasets: Dataset[]
    currentDataset: Dataset | null
    currentImageData: ImageData | null
    imageMetadata: ImageMetadata | null
    datasetStats: Record<string, DatasetStats>

    // 加载状态
    loadingStates: {
        datasets: LoadingState
        imageData: LoadingState
        metadata: LoadingState
        stats: LoadingState
    }

    // 错误状态
    errors: {
        datasets: ErrorInfo | null
        imageData: ErrorInfo | null
        metadata: ErrorInfo | null
        stats: ErrorInfo | null
    }

    // 缓存
    cache: {
        datasets: CacheEntry<Dataset[]> | null
        images: Map<string, CacheEntry<ImageData>>
        metadata: Map<string, CacheEntry<ImageMetadata>>
        stats: Map<string, CacheEntry<DatasetStats>>
    }

    // 配置
    config: {
        cacheTimeout: number // 缓存超时时间（毫秒）
        enableCache: boolean
        retryAttempts: number
    }

    // Actions
    loadDatasets: (forceRefresh?: boolean) => Promise<void>
    loadDataset: (datasetId: string, forceRefresh?: boolean) => Promise<void>
    loadImageData: (imageId: string, forceRefresh?: boolean) => Promise<void>
    loadImageMetadata: (imageId: string, forceRefresh?: boolean) => Promise<void>
    loadDatasetStats: (datasetId: string, forceRefresh?: boolean) => Promise<void>
    setCurrentImage: (imageData: ImageData) => void
    setCurrentDataset: (dataset: Dataset) => void
    clearError: (errorType?: keyof ImageStore['errors']) => void
    clearCache: (cacheType?: keyof ImageStore['cache']) => void
    updateConfig: (config: Partial<ImageStore['config']>) => void

    // 缓存辅助方法
    getCachedData: <T>(cache: CacheEntry<T> | null) => T | null
    setCachedData: <T>(data: T, timeout?: number) => CacheEntry<T>
    isCacheValid: <T>(cache: CacheEntry<T> | null) => boolean
}

// 默认配置
const defaultConfig = {
    cacheTimeout: 5 * 60 * 1000, // 5分钟
    enableCache: true,
    retryAttempts: 3
}

// 创建错误信息
const createErrorInfo = (error: unknown): ErrorInfo => {
    if (error instanceof ApiClientError) {
        return {
            message: error.message,
            code: error.code,
            details: error.details,
            timestamp: Date.now()
        }
    }

    if (error instanceof Error) {
        return {
            message: error.message,
            timestamp: Date.now()
        }
    }

    return {
        message: '未知错误',
        timestamp: Date.now()
    }
}

export const useImageStore = create<ImageStore>()(
    subscribeWithSelector((set, get) => ({
        // 初始状态
        datasets: [],
        currentDataset: null,
        currentImageData: null,
        imageMetadata: null,
        datasetStats: {},

        loadingStates: {
            datasets: 'idle',
            imageData: 'idle',
            metadata: 'idle',
            stats: 'idle'
        },

        errors: {
            datasets: null,
            imageData: null,
            metadata: null,
            stats: null
        },

        cache: {
            datasets: null,
            images: new Map(),
            metadata: new Map(),
            stats: new Map()
        },

        config: { ...defaultConfig },

        // 缓存辅助方法
        getCachedData: <T>(cache: CacheEntry<T> | null): T | null => {
            const store = get()
            if (!store.config.enableCache || !cache) return null
            return store.isCacheValid(cache) ? cache.data : null
        },

        setCachedData: <T>(data: T, timeout?: number): CacheEntry<T> => {
            const store = get()
            const cacheTimeout = timeout || store.config.cacheTimeout
            const now = Date.now()
            return {
                data,
                timestamp: now,
                expiresAt: now + cacheTimeout
            }
        },

        isCacheValid: <T>(cache: CacheEntry<T> | null): boolean => {
            if (!cache) return false
            return Date.now() < cache.expiresAt
        },

        // Actions
        loadDatasets: async (forceRefresh = false) => {
            const store = get()

            // 检查缓存
            if (!forceRefresh && store.config.enableCache) {
                const cachedData = store.getCachedData(store.cache.datasets)
                if (cachedData) {
                    set({ datasets: cachedData })
                    return
                }
            }

            set(state => ({
                loadingStates: { ...state.loadingStates, datasets: 'loading' },
                errors: { ...state.errors, datasets: null }
            }))

            try {
                const apiClient = await getApiClient()
                const datasets = await apiClient.getDatasets()
                const cacheEntry = store.setCachedData(datasets)

                set(state => ({
                    datasets,
                    loadingStates: { ...state.loadingStates, datasets: 'success' },
                    cache: { ...state.cache, datasets: cacheEntry }
                }))
            } catch (error) {
                const errorInfo = createErrorInfo(error)
                set(state => ({
                    loadingStates: { ...state.loadingStates, datasets: 'error' },
                    errors: { ...state.errors, datasets: errorInfo }
                }))
                throw error
            }
        },

        loadDataset: async (datasetId: string, forceRefresh = false) => {
            try {
                const apiClient = await getApiClient()
                const dataset = await apiClient.getDataset(datasetId)
                set({ currentDataset: dataset })
            } catch (error) {
                const errorInfo = createErrorInfo(error)
                set(state => ({
                    errors: { ...state.errors, datasets: errorInfo }
                }))
                throw error
            }
        },

        loadImageData: async (imageId: string, forceRefresh = false) => {
            const store = get()

            // 检查缓存
            if (!forceRefresh && store.config.enableCache) {
                const cachedData = store.getCachedData(store.cache.images.get(imageId) || null)
                if (cachedData) {
                    set({ currentImageData: cachedData })
                    return
                }
            }

            set(state => ({
                loadingStates: { ...state.loadingStates, imageData: 'loading' },
                errors: { ...state.errors, imageData: null }
            }))

            try {
                const apiClient = await getApiClient()
                const imageData = await apiClient.getImageData(imageId)
                const cacheEntry = store.setCachedData(imageData)

                set(state => ({
                    currentImageData: imageData,
                    loadingStates: { ...state.loadingStates, imageData: 'success' },
                    cache: {
                        ...state.cache,
                        images: new Map(state.cache.images).set(imageId, cacheEntry)
                    }
                }))
            } catch (error) {
                const errorInfo = createErrorInfo(error)
                set(state => ({
                    loadingStates: { ...state.loadingStates, imageData: 'error' },
                    errors: { ...state.errors, imageData: errorInfo }
                }))
                throw error
            }
        },

        loadImageMetadata: async (imageId: string, forceRefresh = false) => {
            const store = get()

            // 检查缓存
            if (!forceRefresh && store.config.enableCache) {
                const cachedData = store.getCachedData(store.cache.metadata.get(imageId) || null)
                if (cachedData) {
                    set({ imageMetadata: cachedData })
                    return
                }
            }

            set(state => ({
                loadingStates: { ...state.loadingStates, metadata: 'loading' },
                errors: { ...state.errors, metadata: null }
            }))

            try {
                const apiClient = await getApiClient()
                const metadata = await apiClient.getImageMetadata(imageId)
                const cacheEntry = store.setCachedData(metadata)

                set(state => ({
                    imageMetadata: metadata,
                    loadingStates: { ...state.loadingStates, metadata: 'success' },
                    cache: {
                        ...state.cache,
                        metadata: new Map(state.cache.metadata).set(imageId, cacheEntry)
                    }
                }))
            } catch (error) {
                const errorInfo = createErrorInfo(error)
                set(state => ({
                    loadingStates: { ...state.loadingStates, metadata: 'error' },
                    errors: { ...state.errors, metadata: errorInfo }
                }))
                throw error
            }
        },

        loadDatasetStats: async (datasetId: string, forceRefresh = false) => {
            const store = get()

            // 检查缓存
            if (!forceRefresh && store.config.enableCache) {
                const cachedData = store.getCachedData(store.cache.stats.get(datasetId) || null)
                if (cachedData) {
                    set(state => ({
                        datasetStats: { ...state.datasetStats, [datasetId]: cachedData }
                    }))
                    return
                }
            }

            set(state => ({
                loadingStates: { ...state.loadingStates, stats: 'loading' },
                errors: { ...state.errors, stats: null }
            }))

            try {
                const apiClient = await getApiClient()
                const stats = await apiClient.getDatasetStats(datasetId)
                const cacheEntry = store.setCachedData(stats)

                set(state => ({
                    datasetStats: { ...state.datasetStats, [datasetId]: stats },
                    loadingStates: { ...state.loadingStates, stats: 'success' },
                    cache: {
                        ...state.cache,
                        stats: new Map(state.cache.stats).set(datasetId, cacheEntry)
                    }
                }))
            } catch (error) {
                const errorInfo = createErrorInfo(error)
                set(state => ({
                    loadingStates: { ...state.loadingStates, stats: 'error' },
                    errors: { ...state.errors, stats: errorInfo }
                }))
                throw error
            }
        },

        setCurrentImage: (imageData: ImageData) => {
            set({ currentImageData: imageData })
        },

        setCurrentDataset: (dataset: Dataset) => {
            set({ currentDataset: dataset })
        },

        clearError: (errorType?: keyof ImageStore['errors']) => {
            if (errorType) {
                set(state => ({
                    errors: { ...state.errors, [errorType]: null }
                }))
            } else {
                set({
                    errors: {
                        datasets: null,
                        imageData: null,
                        metadata: null,
                        stats: null
                    }
                })
            }
        },

        clearCache: (cacheType?: keyof ImageStore['cache']) => {
            if (cacheType) {
                set(state => ({
                    cache: {
                        ...state.cache,
                        [cacheType]: cacheType === 'datasets' ? null : new Map()
                    }
                }))
            } else {
                set({
                    cache: {
                        datasets: null,
                        images: new Map(),
                        metadata: new Map(),
                        stats: new Map()
                    }
                })
            }
        },

        updateConfig: (newConfig: Partial<ImageStore['config']>) => {
            set(state => ({
                config: { ...state.config, ...newConfig }
            }))
        }
    }))
)